package top.codedance.iotp.server.net.handle;

import top.codedance.iotp.common.constent.Command;
import top.codedance.iotp.common.entity.CommonEntity;
import top.codedance.iotp.common.util.AsymmetricEncryption;
import top.codedance.iotp.server.ServerApplication;
import top.codedance.iotp.server.net.TcpServer;
import top.codedance.iotp.server.net.session.Session;
import cd.io.netty.channel.ChannelHandlerContext;
import cd.io.netty.channel.ChannelPromise;
import cd.io.netty.channel.SimpleChannelInboundHandler;
import org.apache.log4j.Logger;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class RSAEncryptChannelHandler extends SimpleChannelInboundHandler<CommonEntity> {

    private static Logger logger = ServerApplication.getLogger(RSAEncryptChannelHandler.class);

    @Override
    protected void messageReceived(ChannelHandlerContext channelHandlerContext, CommonEntity commonEntity) throws Exception {
        if(!Arrays.asList(Command.NO_ENCRYPT_CMDS).contains(Short.valueOf(commonEntity.getCommand())) && commonEntity.getBody() != null) {
            Session session = TcpServer.sessionManager.getSessionById(channelHandlerContext.channel().id().toString());
            String privateKey = session.getKeyStringPair().getPrivateKey();
            try {
                String decryptBody = AsymmetricEncryption.decrypt(commonEntity.getBody(), privateKey);
                commonEntity.setBody(decryptBody.getBytes(StandardCharsets.UTF_8));
                logger.debug("****************************************************************************");
                logger.debug(new String(commonEntity.getBody(), StandardCharsets.UTF_8));
                logger.debug("****************************************************************************");
                channelHandlerContext.fireChannelRead(commonEntity.build()); //向后传递
            }catch (Exception ex){
                logger.debug("****************************************************************************");
                logger.debug(new String(commonEntity.getBody(), StandardCharsets.UTF_8));
                logger.debug("****************************************************************************");
                logger.debug(ex.getMessage());
            }
        }else{
            channelHandlerContext.fireChannelRead(commonEntity.build()); //向后传递
        }
    }

    @Override
    public void write(ChannelHandlerContext channelHandlerContext, Object var2, ChannelPromise var3) throws Exception{
        if(var2 instanceof CommonEntity){
            CommonEntity commonEntity = (CommonEntity)var2;
            if(!Arrays.asList(Command.NO_ENCRYPT_CMDS).contains(Short.valueOf(commonEntity.getCommand())) && commonEntity.getBody() != null) {
                byte[] body = commonEntity.getBody();
                logger.debug("****************************************************************************");
                logger.debug(new String(commonEntity.getBody(), StandardCharsets.UTF_8));
                logger.debug("****************************************************************************");
                Session session = TcpServer.sessionManager.getSessionById(channelHandlerContext.channel().id().toString());
                String publicKey = session.getClientPublicKey();
                try {
                    String encryptBody = AsymmetricEncryption.encrypt(body, publicKey);
                    commonEntity.setBody(encryptBody.getBytes(StandardCharsets.UTF_8));
                    super.write(channelHandlerContext, commonEntity.build(), var3);
                } catch (Exception e) {
                    logger.debug("****************************************************************************");
                    logger.debug(new String(commonEntity.getBody(), StandardCharsets.UTF_8));
                    logger.debug("****************************************************************************");
                    logger.debug(e.getMessage());
                }
            }else{
                super.write(channelHandlerContext, var2, var3);
            }
        }else{
            super.write(channelHandlerContext, var2, var3);
        }
    }
}
